package com.taotao.complier.math;

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * 简单数学算术式 的词法分析器
 *
 * @author fanbeibei
 * @date 2020/9/6 13:21
 */
public class SimpleMathExpressionLexer {

    private String expression;

    public SimpleMathExpressionLexer(String expression) {
        if (null == expression || Objects.equals("", expression.trim())) {
            throw new IllegalStateException();
        }

        this.expression = expression;
    }


    /**
     * 分词
     *
     * @return
     */
    public List<Term> lex() {
        List<Term> terms = new LinkedList<>();
        int expressionLen = expression.length();
        int lineNo = 0;
        int linePos = 0;
        for (int i = 0; i < expressionLen; i++) {
            switch (expression.charAt(i)) {
                case ' ':
                    linePos++;
                    break;
                case '\n':
                    terms.add(new Term(Token.OP_PLUS, Token.OP_PLUS.getCode(), lineNo, linePos));
                    linePos++;
                    break;
                case '\r':
                    terms.add(new Term(Token.OP_PLUS, Token.OP_PLUS.getCode(), lineNo, linePos));
                    linePos++;
                    break;
                case '+':
                    terms.add(new Term(Token.OP_PLUS, Token.OP_PLUS.getCode(), lineNo, linePos));
                    linePos++;
                    break;
                case '-':
                    terms.add(new Term(Token.OP_SUBTRACT, Token.OP_SUBTRACT.getCode(), lineNo, linePos));
                    linePos++;
                    break;
                case '/':
                    terms.add(new Term(Token.OP_DIVIDE, Token.OP_DIVIDE.getCode(), lineNo, linePos));
                    linePos++;
                    break;
                case '*':
                    terms.add(new Term(Token.OP_MULTIPLY, Token.OP_MULTIPLY.getCode(), lineNo, linePos));
                    linePos++;
                    break;
                default:
                    if (Character.isDigit(expression.charAt(linePos))) {
                        int numStart = linePos;
                        while (linePos < expressionLen - 1 && Character.isDigit(expression.charAt(linePos)) && Character.isDigit(expression.charAt(linePos + 1))) {
                            linePos++;
                            i++;
                        }

                        terms.add(new Term(Token.NUM, expression.substring(numStart, linePos + 1), lineNo, numStart));
                        linePos++;
                    }   else {
                        throw new IllegalStateException("error  char :" + expression.charAt(linePos) + ",at line " + lineNo + ",pos:" + linePos);
                    }
            }
        }


        return terms;

    }


}
